#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fcntl.h>
int connect_ser(char *ipstr, int port)
{
    if(ipstr==NULL || port<= 0)return -1;
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(sockfd == -1)return -1;
    struct sockaddr_in saddr;
    memset(&saddr, 0, sizeof(saddr));
    saddr.sin_family = AF_INET;
    saddr.sin_port = htons(port);
    saddr.sin_addr.s_addr = inet_addr(ipstr);
    int res = connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));
    if(res == -1)return -1;
    return sockfd;
}
void get_arg(int argc, char * argv[], char **s, int *p)
{
    if(argc<=1 || argv==NULL || s==NULL || p==NULL)return;
    for(int i = 1; i < argc; ++i)
    {
        if(strncmp(argv[i], "ip=", 3)==0)
        {
            /* 检查ip地址是否合法，将来完成 */
            *s = argv[i] + 3;
            continue;
        }
        if(strncmp(argv[i], "port=", 5)==0)
        {
            /* 安全检查，将来完成 */
            *p = atoi(argv[i]+5);
            continue;
        }
    }
}
char * get_cmd(char buff[], char * myargv[])
{
    if(buff == NULL || myargv == NULL)return NULL;
    char * s = strtok(buff, " ");
    int i = 0;
    while(s != NULL)
    {
        myargv[i++] = s;
        s = strtok(NULL, " ");
    }
    return myargv[0];
}
void recv_file(int c, char * name, char *s)
{
    if(NULL == name || NULL == s)return;
    send(c, s, strlen(s), 0);
    char status[32] = {0};
    int num = recv(c, status, 31, 0);
    if(num <= 0)
    {
        printf("ser closed\n");
        return;
    }
    if(strncmp(status, "ok#", 3)!=0)
    {
        printf("file not exists, or can't download\n");
        return;
    }
    int filesize = atoi(status+3);  //ok#0
    int fd = open(name, O_WRONLY|O_CREAT, 6000);
    if(filesize == 0)
    {
        send(c, "err", 3, 0);
        close(fd);
        return;
    }
    if(fd == -1)
    {
        send(c, "err", 3, 0);
        return;
    }
    send(c, "ok#", 3, 0);
    int curr_size = 0;
    float f = 0.0;
    num = 0;
    char data[1024];
    while(1)
    {
        int num = recv(c, data, 1024, 0);
        if(num <= 0)
        {
            printf("ser closed\n");
            break;
        }
        write(fd, data, num);
        curr_size += num;
        f = curr_size * 100.0 / filesize;
        printf("down %s :%.1f%%\r", name, f);
        fflush(stdout);
        if(curr_size >= filesize)
        {
            printf("\n");
            break;
        }
    }
}
int main(int argc, char * argv[])
{
    char * ipstr = "127.0.0.1"; //default value
    int port = 6000;            //default value
    get_arg(argc, argv, &ipstr, &port);
    int sockfd = connect_ser(ipstr, port);
    if(sockfd == -1)
    {
        printf("connect to server failed, ip: %s, port: %d\n", ipstr, port);
        exit(0);
    }
    while (1)
    {
        char buff[128] = {0};
        printf("connect: %s >> ", ipstr);
        fflush(stdout);

        fgets(buff, 128, stdin);
        buff[strlen(buff)-1] = 0;

        char cmd_buff[128] = {0};
        strcpy(cmd_buff, buff);

        char * myargv[10] = {0};
        char * cmd = get_cmd(buff, myargv);

        if(strcmp(cmd, "get")==0)
        {
            /* 下载 */
            recv_file(sockfd, myargv[1], cmd_buff); //3rd arg should be cmd_buff, can't be 'cmd'! 'cmd' maybe not complete, such as "get xxx.c", 'cmd' only is 'get', it lose 'xxx.c'!
        }
        else if(strcmp(cmd, "up")==0)
        {

        }
        else if(strcmp(cmd, "end")==0)
        {
            break;
        }
        else
        {
            char recv_buff[1024] = {0};
            send(sockfd, cmd_buff, strlen(cmd_buff), 0);
            int num = recv(sockfd, recv_buff, 1023, 0);
            if(num <= 0)
            {
                printf("ser closed\n");
                break;
            }
            if(strncmp(recv_buff, "ok#", 3)==0)
            {
                printf("%s\n", recv_buff+3);
            }
            else
            {
                printf("exec failed\n");
            }
        }
    /*  if (strncmp(buff, "end", 3) == 0)
        {
            break;
        }
        send(sockfd, buff, strlen(buff), 0);
        memset(buff, 0, 128);
        recv(sockfd, buff, 127, 0);
        printf("buff = %s\n", buff);
    }
    */
    }
    close(sockfd);
}